--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:    13:09:05 10/22/05
-- Design Name:    
-- Module Name:    KeyboardReceiverVHDL - Behavioral
-- Project Name:   
-- Target Device:  
-- Tool versions:  
-- Description:
--
-- Dependencies:
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
-- 
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity KeyboardReceiverVHDL is
    Port ( clk : in std_logic;
           SCLK : in std_logic;
           SDA : in std_logic;
           DataOut : out std_logic_vector(7 downto 0);
           DataReady : out std_logic;
			  Reset : in std_logic);
end KeyboardReceiverVHDL;

architecture Behavioral of KeyboardReceiverVHDL is

	COMPONENT fredgedetect
	PORT(
		clk : IN std_logic;
		Edge : IN std_logic;          
		FED : OUT std_logic;
		RED : OUT std_logic
		);
	END COMPONENT;

	signal RED : std_logic;
	signal DATA : std_logic_vector(8 downto 0) := "000000000";
	signal DataOk : std_logic := '0';
	signal DataCheck : std_logic;

	type state is(
		stIdle,
		stGotStart,
		stData,
		stGotStop);
	
	signal stCur : state := stIdle;
	signal stNext : state;

	signal Bitpos : std_logic_vector(3 downto 0):= "0000";
	signal toss : std_logic;
	signal DataSync : std_logic_vector(2 downto 0);

begin

	Inst_fredgedetect: fredgedetect PORT MAP(
		clk => clk,
		Edge => SCLK,
		FED => toss,
		RED => RED
	);

	process(clk)
	begin
		if(clk = '0' and clk'event) Then
			stCur <= stNext;
		end if;
	end process;

	process(clk)
	begin
		if(clk = '0' and clk'event) then
			DataSync(0) <= SDA;
			DataSync(1) <= DataSync(0);
			DataSync(2) <= DataSync(1);
		end if;
	end process;

	process(clk, red, DataSync(2), sclk)
	begin
		if(clk = '1' and clk'event) then
			if(reset = '1') then
				stNext <= stIdle;
			else	
				case stCur is
					when stIdle =>
						DataCheck <= '1';
						bitpos <= "0000";
						if(RED = '1' and DataSync(2) = '0') then
							stNext <= stGotStart;
							Data <= "000000000";
						else
							stNext <= stIdle;
						end if;
					when stGotStart =>
						DataCheck <= '0';
						
						if(RED = '1') then
							stNext <= stData;
						else
							stNExt <= stGotStart;
						end if;
					when stData =>
						DataCheck <= '0';
						case bitpos is
							when "0000" =>
								data(0) <= DataSync(2);
								bitpos <= bitpos + 1;
								stNext <= stGotStart;
							when "0001" =>
								data(1) <= DataSync(2);
								bitpos <= bitpos + 1;
								stNext <= stGotStart;
							when "0010" =>
								data(2) <= DataSync(2);
								bitpos <= bitpos + 1;
								stNext <= stGotStart;
							when "0011" =>
								data(3) <= DataSync(2);
								bitpos <= bitpos + 1;
								stNext <= stGotStart;
							when "0100" =>
								data(4) <= DataSync(2);
								bitpos <= bitpos + 1;
								stNext <= stGotStart;
							when "0101" =>
								data(5) <= DataSync(2);
								bitpos <= bitpos + 1;
								stNext <= stGotStart;
							when "0110" =>
								data(6) <= DataSync(2);
								bitpos <= bitpos + 1;
								stNext <= stGotStart;
							when "0111" =>
								data(7) <= DataSync(2);
								bitpos <= bitpos + 1;
								stNext <= stGotStart;
							when "1000" =>
								data(8) <= DataSync(2);
								stNext <= stGotStop;
							when others =>
								stNext <= stGotStop;
						end case;	
					when stGotStop =>
						DataCheck <= '0';
						if(RED = '1' and DataSync(2) = '1') then
							stNext <= stIdle;
						else
							stNext <= stGotStop;
						end if;		
				end case;
			end if;
		end if;
	end process;			


	process(clk, DataCheck)
	begin
		if(clk = '0' and clk'event) then
			if(DataCheck = '1') then
				DataReady <= DataOk;
			else
				DataReady <= '0';
			end if;
		end if;
	end process;
				
	DataOk <= (Data(0) xor Data(1) xor Data(2) xor Data(3) xor data(4) xor data(5) xor data(6) xor data(7)) xor data(8);							
	DataOut <= Data(7 downto 0);
	
end Behavioral;
